package com.note.app.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.houbb.sensitive.word.core.SensitiveWordHelper;
import com.note.app.document.NoteContent;
import com.note.app.dto.ai.AICreateNoteRequestDTO;
import com.note.app.dto.ai.AIEditNoteRequestDTO;
import com.note.app.dto.ai.AIChatRequestDTO;
import com.note.app.dto.ai.AIResponseDTO;
import com.note.app.mapper.AIConversationMapper;
import com.note.app.mapper.NoteMapper;
import com.note.app.repository.NoteContentRepository;
import com.note.app.service.AIService;
import com.note.common.domain.AIConversation;
import com.note.common.domain.Note;
import com.note.common.exception.BusinessException;
import com.note.common.vo.PageResult;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import java.util.Spliterator;
import jakarta.annotation.PostConstruct;

/**
 * AI服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AIServiceImpl implements AIService {

    private final AIConversationMapper aiConversationMapper;
    private final NoteMapper noteMapper;
    private final NoteContentRepository noteContentRepository;
    private final ObjectMapper objectMapper;
    @Autowired
    @Qualifier("externalRestTemplate")
    private RestTemplate restTemplate;

    @Value("${deepseek.api.key:sk-a48a084413d9402baa30bddfb05d0a3e}")
    private String apiKey;

    @Value("${deepseek.api.url:https://api.deepseek.com/chat/completions}")
    private String apiUrl;
    
    @Value("${sensitive.word.threshold:10}")
    private int sensitiveWordThreshold;

    @PostConstruct
    public void init() {
        // 检查API配置
        log.info("AI服务初始化 - API URL: {}", apiUrl);
        log.info("AI服务初始化 - API Key: {}", apiKey.substring(0, 5) + "***");
        
        // 检查RestTemplate注入
        if (restTemplate == null) {
            log.error("RestTemplate未注入，请检查配置");
        } else {
            log.info("RestTemplate类型: {}", restTemplate.getClass().getName());
        }
    }

    @Override
    public AIResponseDTO generateNoteContent(Long userId, AICreateNoteRequestDTO request) {
        try {
            log.info("开始生成笔记内容 - 用户ID: {}, 模式: {}, 提示词: {}", userId, request.getMode(), request.getPrompt());
            
            // 敏感词过滤
            checkSensitiveWords(request.getPrompt(), "提示词");

            // 调用DeepSeek API
            Map<String, Object> response = callDeepSeekAPI(buildCreateNotePrompt(request), request.getExtraParams());

            // 解析响应
            AIResponseDTO aiResponse = parseCreateNoteResponse(response, request.getMode());

            // 保存对话历史
            AIConversation conversation = saveConversationHistory(userId, null, request.getMode(),
                    request.getPrompt(), request.getExtraParams(), response);

            // 设置会话ID
            aiResponse.setConversationId(conversation.getId());

            log.info("笔记内容生成成功 - 用户ID: {}, 会话ID: {}", userId, conversation.getId());
            return aiResponse;
        } catch (Exception e) {
            log.error("生成笔记内容失败", e);
            throw new RuntimeException("生成笔记内容失败: " + e.getMessage());
        }
    }

    @Override
    public AIResponseDTO enhanceNoteContent(Long userId, AIEditNoteRequestDTO request) {
        try {
            log.info("开始增强笔记内容 - 用户ID: {}, 笔记ID: {}, 模式: {}", userId, request.getNoteId(), request.getMode());
            
            // 敏感词过滤
            checkSensitiveWords(request.getPrompt(), "提示词");

            String noteContent;
            String noteTitle;

            // 如果没有直接提供内容，则从数据库获取
            if (!request.getIncludeContent() || request.getContent() == null) {
                // 查询笔记
                log.debug("未提供笔记内容，从数据库获取 - 笔记ID: {}", request.getNoteId());
                Note note = noteMapper.selectById(request.getNoteId());
                if (note == null) {
                    log.warn("未找到笔记 - 笔记ID: {}", request.getNoteId());
                    throw new RuntimeException("未找到笔记");
                }

                // 检查权限
                if (!note.getUserId().equals(userId)) {
                    log.warn("无权访问笔记 - 用户ID: {}, 笔记所有者ID: {}", userId, note.getUserId());
                    throw new RuntimeException("无权访问该笔记");
                }

                noteTitle = note.getTitle();

                // 获取笔记内容
                log.debug("获取笔记内容 - 内容ID: {}", note.getContentId());
                Optional<NoteContent> contentOpt = noteContentRepository.findById(note.getContentId());
                if (contentOpt.isEmpty()) {
                    log.warn("未找到笔记内容 - 内容ID: {}", note.getContentId());
                    throw new RuntimeException("未找到笔记内容");
                }

                noteContent = contentOpt.get().getContent();
                log.debug("成功获取笔记内容 - 笔记标题: {}, 内容长度: {}", noteTitle, noteContent.length());
            } else {
                noteContent = request.getContent();
                noteTitle = request.getTitle();
                log.debug("使用请求中提供的笔记内容 - 内容长度: {}", noteContent.length());
            }

            // 调用DeepSeek API
            log.debug("开始构建编辑笔记提示词 - 模式: {}", request.getMode());
            String promptData = buildEditNotePrompt(request.getMode(), noteTitle, noteContent, request.getPrompt());
            log.debug("调用DeepSeek API - URL: {}", apiUrl);
            Map<String, Object> response = callDeepSeekAPI(promptData, request.getExtraParams());

            // 解析响应
            log.debug("开始解析编辑笔记响应");
            AIResponseDTO aiResponse = parseEditNoteResponse(response, request.getMode());

            // 保存对话历史
            AIConversation conversation = saveConversationHistory(userId, request.getNoteId(), request.getMode(),
                    request.getPrompt(), request.getExtraParams(), response);

            // 设置会话ID
            aiResponse.setConversationId(conversation.getId());

            log.info("笔记内容增强成功 - 用户ID: {}, 笔记ID: {}, 会话ID: {}", userId, request.getNoteId(), conversation.getId());
            return aiResponse;
        } catch (Exception e) {
            log.error("增强笔记内容失败", e);
            throw new RuntimeException("增强笔记内容失败: " + e.getMessage());
        }
    }

    @Override
    public Object getUserConversations(Long userId, Integer page, Integer size) {
        Page<AIConversation> pageParam = new Page<>(page, size);
        // 包装类型转换
        com.baomidou.mybatisplus.core.metadata.IPage<AIConversation> iPage = aiConversationMapper
                .selectPageByUserId(pageParam, userId);

        return PageResult.of(
                iPage.getRecords(),
                iPage.getTotal(),
                iPage.getCurrent() - 1,
                iPage.getSize());
    }

    @Override
    public List<AIConversation> getRecentConversations(Long userId, Integer limit) {
        return aiConversationMapper.selectRecentByUserId(userId, limit);
    }

    @Override
    public AIConversation getConversationById(Long conversationId) {
        return aiConversationMapper.selectById(conversationId);
    }

    @Override
    public boolean deleteConversation(Long userId, Long conversationId) {
        LambdaQueryWrapper<AIConversation> wrapper = new LambdaQueryWrapper<AIConversation>()
                .eq(AIConversation::getId, conversationId)
                .eq(AIConversation::getUserId, userId);

        AIConversation conversation = new AIConversation();
        conversation.setDeleted(1);

        return aiConversationMapper.update(conversation, wrapper) > 0;
    }

    @Override
    public AIResponseDTO chatWithAI(Long userId, AIChatRequestDTO request) {
        try {
            log.info("开始聊天 - 用户ID: {}, 消息条数: {}", userId, 
                request.getMessages() != null ? request.getMessages().size() : 0);
            
            // 敏感词过滤用户消息
            if (request.getMessages() != null && !request.getMessages().isEmpty()) {
                for (AIChatRequestDTO.ChatMessage message : request.getMessages()) {
                    if ("user".equals(message.getRole())) {
                        checkSensitiveWords(message.getContent(), "聊天内容");
                    }
                }
            }

            // 调用DeepSeek API
            Map<String, Object> response = callDeepSeekAPI(buildChatPrompt(request), request.getExtraParams());

            // 解析响应
            AIResponseDTO aiResponse = parseChatResponse(response);

            // 保存对话历史
            AIConversation conversation = saveConversationHistory(userId, null, "CHAT",
                    getLatestUserMessage(request), request.getExtraParams(), response);

            // 设置会话ID
            aiResponse.setConversationId(conversation.getId());

            log.info("聊天完成 - 用户ID: {}, 会话ID: {}", userId, conversation.getId());
            return aiResponse;
        } catch (Exception e) {
            log.error("聊天失败", e);
            throw new RuntimeException("聊天失败: " + e.getMessage());
        }
    }
    
    /**
     * 检查文本是否包含敏感词，超过阈值抛出异常
     * @param text 待检查文本
     * @param fieldName 字段名称（用于错误提示）
     */
    private void checkSensitiveWords(String text, String fieldName) {
        if (text == null || text.isEmpty()) {
            return;
        }
        
        try {
            List<String> sensitiveWords = SensitiveWordHelper.findAll(text);
            
            if (sensitiveWords.size() > sensitiveWordThreshold) {
                log.warn("敏感词检测失败 - {}: 违规词数量: {}, 违规词: {}", fieldName, sensitiveWords.size(), 
                         sensitiveWords.size() > 10 ? sensitiveWords.subList(0, 10) + "..." : sensitiveWords);
                throw new BusinessException(fieldName + "包含过多违规内容，请修改后重试，违规词数量：" + sensitiveWords.size());
            }
            
            // 如果有敏感词但未超过阈值，记录日志但允许通过
            if (!sensitiveWords.isEmpty()) {
                log.info("敏感词检测通过但包含敏感词 - {}: 敏感词数量: {}, 敏感词: {}", fieldName, sensitiveWords.size(), sensitiveWords);
            }
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("敏感词检测异常", e);
            // 出现异常时，继续处理，避免阻断用户操作
        }
    }

    /**
     * 构建创建笔记的提示词
     */
    private String buildCreateNotePrompt(AICreateNoteRequestDTO request) {
        String mode = request.getMode();
        String prompt = request.getPrompt();
        String language = request.getLanguage();

        StringBuilder systemPrompt = new StringBuilder();
        systemPrompt.append("你是一个笔记写作助手，根据用户的提示创建笔记内容。");
        systemPrompt.append("请分析用户的提示，并以JSON格式返回生成的笔记内容。");
        systemPrompt.append("用户的语言偏好是：").append(language).append("。");
        systemPrompt.append("\n\n返回的JSON必须包含以下字段：");
        systemPrompt.append("\n- title: 笔记标题");
        systemPrompt.append("\n- content: 笔记正文内容");

        // 根据不同模式构建不同的提示词
        switch (mode) {
            case "CREATE_NOTE":
                systemPrompt.append("\n- tags: 建议的标签列表，最多5个");
                systemPrompt.append("\n\n请保证返回的是一个有效的JSON结构，所有文本必须正确转义。");
                systemPrompt.append("\n\n示例输出格式：");
                systemPrompt.append("\n```json");
                systemPrompt.append("\n{");
                systemPrompt.append("\n  \"title\": \"生成的标题\",");
                systemPrompt.append("\n  \"content\": \"生成的笔记内容...\",");
                systemPrompt.append("\n  \"tags\": [\"标签1\", \"标签2\", \"标签3\"]");
                systemPrompt.append("\n}");
                systemPrompt.append("\n```");
                break;

            case "TECHNICAL_TUTORIAL":
                systemPrompt.append("\n- sections: 教程章节数组，每个章节包含title和content字段");
                systemPrompt.append("\n- codeExamples: 代码示例数组，每个示例包含language、description和code字段");
                systemPrompt.append("\n- tags: 建议的标签列表，最多5个");
                systemPrompt.append("\n\n请生成一个技术教程，包含清晰的解释和代码示例。");
                systemPrompt.append("\n\n示例输出格式：");
                systemPrompt.append("\n```json");
                systemPrompt.append("\n{");
                systemPrompt.append("\n  \"title\": \"技术教程标题\",");
                systemPrompt.append("\n  \"content\": \"教程简介内容...\",");
                systemPrompt.append("\n  \"sections\": [");
                systemPrompt.append("\n    {\"title\": \"第一章节标题\", \"content\": \"章节内容...\"},");
                systemPrompt.append("\n    {\"title\": \"第二章节标题\", \"content\": \"章节内容...\"}");
                systemPrompt.append("\n  ],");
                systemPrompt.append("\n  \"codeExamples\": [");
                systemPrompt.append(
                        "\n    {\"language\": \"javascript\", \"description\": \"示例描述\", \"code\": \"console.log('Hello');\\n\"}");
                systemPrompt.append("\n  ],");
                systemPrompt.append("\n  \"tags\": [\"技术\", \"教程\", \"编程\"]");
                systemPrompt.append("\n}");
                systemPrompt.append("\n```");
                break;

            case "CREATIVE_WRITING":
                systemPrompt.append("\n- genre: 创作类型");
                systemPrompt.append("\n- theme: 主题");
                systemPrompt.append("\n- characters: 角色数组，每个角色包含name、description字段");
                systemPrompt.append("\n- tags: 建议的标签列表，最多5个");
                systemPrompt.append("\n\n请创作一篇有创意的文章，可以是故事、散文或诗歌。");
                systemPrompt.append("\n\n示例输出格式：");
                systemPrompt.append("\n```json");
                systemPrompt.append("\n{");
                systemPrompt.append("\n  \"title\": \"创作标题\",");
                systemPrompt.append("\n  \"content\": \"创作内容...\",");
                systemPrompt.append("\n  \"genre\": \"散文\",");
                systemPrompt.append("\n  \"theme\": \"自然\",");
                systemPrompt.append("\n  \"characters\": [");
                systemPrompt.append("\n    {\"name\": \"角色名\", \"description\": \"角色描述\"}");
                systemPrompt.append("\n  ],");
                systemPrompt.append("\n  \"tags\": [\"创意\", \"文学\", \"散文\"]");
                systemPrompt.append("\n}");
                systemPrompt.append("\n```");
                break;

            default:
                // 默认模式
                systemPrompt.append("\n- tags: 建议的标签列表，最多5个");
                systemPrompt.append("\n\n请保证返回的是一个有效的JSON结构，所有文本必须正确转义。");
                break;
        }

        // 构建用户消息
        String userMessage = prompt;

        // 构建完整请求消息
        List<Map<String, String>> messages = new ArrayList<>();
        messages.add(Map.of("role", "system", "content", systemPrompt.toString()));
        messages.add(Map.of("role", "user", "content", userMessage));

        // 构建请求体
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("model", "deepseek-chat");
        requestBody.put("messages", messages);
        requestBody.put("response_format", Map.of("type", "json_object"));

        try {
            return objectMapper.writeValueAsString(requestBody);
        } catch (Exception e) {
            log.error("构建创建笔记提示词失败", e);
            throw new RuntimeException("构建创建笔记提示词失败", e);
        }
    }

    /**
     * 构建编辑笔记的提示词
     */
    private String buildEditNotePrompt(String mode, String noteTitle, String noteContent, String prompt) {
        StringBuilder systemPrompt = new StringBuilder();
        systemPrompt.append("你是一个笔记编辑助手，根据现有笔记内容和用户的提示对笔记进行增强。");
        systemPrompt.append("请以JSON格式返回处理后的结果。");

        // 根据不同模式构建不同的提示词
        switch (mode) {
            case "SUMMARIZE":
                systemPrompt.append("\n\n任务：总结提供的笔记内容，生成一个简洁的摘要。");
                systemPrompt.append("\n\n返回的JSON必须包含以下字段：");
                systemPrompt.append("\n- summary: 笔记内容的摘要");
                systemPrompt.append("\n- keyPoints: 关键点列表");
                systemPrompt.append("\n\n示例输出格式：");
                systemPrompt.append("\n```json");
                systemPrompt.append("\n{");
                systemPrompt.append("\n  \"summary\": \"摘要内容...\",");
                systemPrompt.append("\n  \"keyPoints\": [\"关键点1\", \"关键点2\", \"关键点3\"]");
                systemPrompt.append("\n}");
                systemPrompt.append("\n```");
                break;

            case "ENHANCE":
                systemPrompt.append("\n\n任务：增强提供的笔记内容，添加更多细节、例子或解释。");
                systemPrompt.append("\n\n返回的JSON必须包含以下字段：");
                systemPrompt.append("\n- enhancedContent: 增强后的完整笔记内容");
                systemPrompt.append("\n- addedSections: 新增加的部分列表");
                systemPrompt.append("\n\n示例输出格式：");
                systemPrompt.append("\n```json");
                systemPrompt.append("\n{");
                systemPrompt.append("\n  \"enhancedContent\": \"增强后的完整内容...\",");
                systemPrompt.append("\n  \"addedSections\": [\"新增部分1\", \"新增部分2\"]");
                systemPrompt.append("\n}");
                systemPrompt.append("\n```");
                break;

            case "EXTRACT_TAGS":
                systemPrompt.append("\n\n任务：从笔记内容中提取关键词作为标签。");
                systemPrompt.append("\n\n返回的JSON必须包含以下字段：");
                systemPrompt.append("\n- tags: 从内容中提取的标签列表，最多10个");
                systemPrompt.append("\n\n示例输出格式：");
                systemPrompt.append("\n```json");
                systemPrompt.append("\n{");
                systemPrompt.append("\n  \"tags\": [\"标签1\", \"标签2\", \"标签3\"]");
                systemPrompt.append("\n}");
                systemPrompt.append("\n```");
                break;

            case "REWRITE":
                systemPrompt.append("\n\n任务：改写笔记内容，保持相同的意思但使用不同的表达方式。");
                systemPrompt.append("\n\n返回的JSON必须包含以下字段：");
                systemPrompt.append("\n- rewrittenContent: 改写后的内容");
                systemPrompt.append("\n\n示例输出格式：");
                systemPrompt.append("\n```json");
                systemPrompt.append("\n{");
                systemPrompt.append("\n  \"rewrittenContent\": \"改写后的内容...\"");
                systemPrompt.append("\n}");
                systemPrompt.append("\n```");
                break;

            default:
                // 默认模式
                systemPrompt.append("\n\n任务：分析笔记内容并提供反馈。");
                systemPrompt.append("\n\n返回的JSON必须包含以下字段：");
                systemPrompt.append("\n- feedback: 对笔记内容的反馈");
                systemPrompt.append("\n\n示例输出格式：");
                systemPrompt.append("\n```json");
                systemPrompt.append("\n{");
                systemPrompt.append("\n  \"feedback\": \"反馈内容...\"");
                systemPrompt.append("\n}");
                systemPrompt.append("\n```");
                break;
        }

        // 构建用户消息
        StringBuilder userMessage = new StringBuilder();
        userMessage.append("笔记标题：").append(noteTitle).append("\n\n");
        userMessage.append("笔记内容：\n").append(noteContent).append("\n\n");

        if (prompt != null && !prompt.isEmpty()) {
            userMessage.append("我的要求：").append(prompt);
        }

        // 构建完整请求消息
        List<Map<String, String>> messages = new ArrayList<>();
        messages.add(Map.of("role", "system", "content", systemPrompt.toString()));
        messages.add(Map.of("role", "user", "content", userMessage.toString()));

        // 构建请求体
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("model", "deepseek-chat");
        requestBody.put("messages", messages);
        requestBody.put("response_format", Map.of("type", "json_object"));

        try {
            return objectMapper.writeValueAsString(requestBody);
        } catch (Exception e) {
            log.error("构建编辑笔记提示词失败", e);
            throw new RuntimeException("构建编辑笔记提示词失败", e);
        }
    }

    /**
     * 构建聊天的提示词
     */
    private String buildChatPrompt(AIChatRequestDTO request) {
        try {
            // 构建用户消息
            List<Map<String, String>> messages = new ArrayList<>();
            
            // 添加系统消息
            messages.add(Map.of("role", "system", "content", "你是一个有帮助的AI助手，可以回答用户的各种问题。"));
            
            // 添加历史消息
            if (request.getMessages() != null && !request.getMessages().isEmpty()) {
                for (AIChatRequestDTO.ChatMessage message : request.getMessages()) {
                    messages.add(Map.of("role", message.getRole(), "content", message.getContent()));
                }
            }
            
            // 构建请求体
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("model", "deepseek-chat");
            requestBody.put("messages", messages);
            
            return objectMapper.writeValueAsString(requestBody);
        } catch (Exception e) {
            log.error("构建聊天提示词失败", e);
            throw new RuntimeException("构建聊天提示词失败", e);
        }
    }

    /**
     * 解析聊天响应
     */
    private AIResponseDTO parseChatResponse(Map<String, Object> response) {
        try {
            log.debug("开始解析聊天响应");

            // 提取AI响应内容
            Map<String, Object> choice = ((List<Map<String, Object>>) response.get("choices")).get(0);
            Map<String, Object> message = (Map<String, Object>) choice.get("message");
            String content = (String) message.get("content");
            log.debug("提取AI响应内容成功 - 内容长度: {}", content.length());

            AIResponseDTO aiResponse = new AIResponseDTO();
            aiResponse.setMode("CHAT");
            aiResponse.setContent(content);

            // 设置元数据
            Map<String, Object> metadataMap = new HashMap<>();
            metadataMap.put("model", response.get("model"));
            metadataMap.put("usage", response.get("usage"));
            aiResponse.setMetadata(objectMapper.writeValueAsString(metadataMap));

            // 设置创建时间
            aiResponse.setCreatedAt(LocalDateTime.now().toString());

            log.debug("聊天响应解析完成");
            return aiResponse;
        } catch (Exception e) {
            log.error("解析聊天响应失败 - 原因: {}", e.getMessage(), e);
            throw new RuntimeException("解析聊天响应失败: " + e.getMessage());
        }
    }

    /**
     * 获取最新的用户消息作为提示词
     */
    private String getLatestUserMessage(AIChatRequestDTO request) {
        if (request.getMessages() == null || request.getMessages().isEmpty()) {
            return "";
        }
        
        // 倒序查找最新的用户消息
        for (int i = request.getMessages().size() - 1; i >= 0; i--) {
            AIChatRequestDTO.ChatMessage message = request.getMessages().get(i);
            if ("user".equals(message.getRole())) {
                return message.getContent();
            }
        }
        
        return request.getMessages().get(request.getMessages().size() - 1).getContent();
    }

    /**
     * 调用DeepSeek API
     */
    private Map<String, Object> callDeepSeekAPI(String requestBody, String extraParams) {
        try {
            log.info("准备调用DeepSeek API - URL: {}", apiUrl);
            log.debug("API请求体长度: {} 字符", requestBody.length());

            // 配置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("Authorization", "Bearer " + apiKey);
            log.debug("已设置请求头: Content-Type={}, Authorization=Bearer ***", MediaType.APPLICATION_JSON);
            
            // 打印完整请求体用于调试
            log.debug("完整API请求体: {}", requestBody);

            // 记录RestTemplate配置
            log.info("使用的RestTemplate实例: {}", restTemplate.getClass().getName());
            log.debug("RestTemplate hashCode: {}", restTemplate.hashCode());

            // 发送请求
            log.debug("开始发送HTTP请求到DeepSeek API - 同步等待响应");
            long startTime = System.currentTimeMillis();
            org.springframework.http.HttpEntity<String> entity = new org.springframework.http.HttpEntity<>(requestBody,
                    headers);

            log.debug("使用的RestTemplate实例: {}", restTemplate.getClass().getName());

            // 使用try-catch包装请求操作以获取更多错误信息
            String responseBody;
            try {
                // 使用exchange方法而不是postForObject，以确保同步处理
                org.springframework.http.ResponseEntity<String> response = 
                    restTemplate.exchange(
                        apiUrl, 
                        org.springframework.http.HttpMethod.POST, 
                        entity, 
                        String.class
                    );
                
                responseBody = response.getBody();
                log.debug("HTTP响应状态码: {}", response.getStatusCode());
                
                // 检查响应体是否为空
                if (responseBody == null || responseBody.isEmpty()) {
                    throw new RuntimeException("DeepSeek API返回空响应体");
                }
            } catch (org.springframework.web.client.ResourceAccessException e) {
                // 资源访问异常，通常是网络或超时问题
                log.error("DeepSeek API资源访问异常: {}", e.getMessage(), e);
                if (e.getCause() instanceof java.net.SocketTimeoutException) {
                    throw new RuntimeException("DeepSeek API请求超时，请稍后重试", e);
                } else if (e.getCause() instanceof java.net.ConnectException) {
                    throw new RuntimeException("无法连接到DeepSeek API服务器", e);
                } else {
                    throw new RuntimeException("DeepSeek API网络错误: " + e.getMessage(), e);
                }
            } catch (org.springframework.web.client.HttpClientErrorException e) {
                // HTTP客户端错误(4xx)
                log.error("DeepSeek API HTTP客户端错误: {} - {}", e.getStatusCode(), e.getResponseBodyAsString(), e);
                throw new RuntimeException("DeepSeek API请求错误: " + e.getStatusCode() + " - " + e.getResponseBodyAsString(), e);
            } catch (org.springframework.web.client.HttpServerErrorException e) {
                // HTTP服务器错误(5xx)
                log.error("DeepSeek API HTTP服务器错误: {} - {}", e.getStatusCode(), e.getResponseBodyAsString(), e);
                throw new RuntimeException("DeepSeek API服务器错误: " + e.getStatusCode() + " - " + e.getResponseBodyAsString(), e);
            } catch (Exception e) {
                // 其他异常
                log.error("DeepSeek API请求异常: {}", e.getMessage(), e);
                throw new RuntimeException("DeepSeek API请求失败: " + e.getMessage(), e);
            }
            
            long endTime = System.currentTimeMillis();
            log.info("DeepSeek API调用完成，耗时: {}ms", (endTime - startTime));

            // 记录完整响应用于调试
            log.debug("完整API响应: {}", responseBody);
            
            // 记录响应片段
            String responseLog = responseBody;
            if (responseLog != null && responseLog.length() > 500) {
                responseLog = responseLog.substring(0, 200) + "..." + responseLog.substring(responseLog.length() - 200);
            }
            log.debug("API响应片段: {}", responseLog);

            // 确保响应不为空
            if (responseBody == null || responseBody.trim().isEmpty()) {
                log.error("DeepSeek API返回空响应");
                throw new RuntimeException("DeepSeek API返回空响应");
            }

            try {
                // 解析响应
                Map<String, Object> responseMap = objectMapper.readValue(responseBody, Map.class);
                log.debug("响应解析成功，包含键: {}", responseMap.keySet());
                
                // 验证响应中包含必要的字段
                if (!responseMap.containsKey("choices") || ((List<?>)responseMap.get("choices")).isEmpty()) {
                    log.error("DeepSeek API响应缺少必要字段: choices");
                    throw new RuntimeException("DeepSeek API响应格式错误：缺少choices字段");
                }
                
                return responseMap;
            } catch (com.fasterxml.jackson.core.JsonParseException e) {
                log.error("DeepSeek API响应JSON解析错误: {}", e.getMessage(), e);
                log.error("无效的JSON响应: {}", responseBody);
                throw new RuntimeException("DeepSeek API返回无效的JSON响应: " + e.getMessage(), e);
            }
        } catch (Exception e) {
            log.error("调用DeepSeek API失败 - 原因: {}", e.getMessage(), e);
            log.error("DeepSeek API调用详情 - URL: {}, API Key: {}", apiUrl, apiKey.substring(0, 5) + "***");
            throw new RuntimeException("调用DeepSeek API失败: " + e.getMessage(), e);
        }
    }

    /**
     * 解析创建笔记模式的响应
     */
    private AIResponseDTO parseCreateNoteResponse(Map<String, Object> response, String mode) {
        try {
            log.debug("开始解析创建笔记响应 - 模式: {}", mode);

            // 提取AI响应内容
            Map<String, Object> choice = ((List<Map<String, Object>>) response.get("choices")).get(0);
            Map<String, Object> message = (Map<String, Object>) choice.get("message");
            String content = (String) message.get("content");
            log.debug("提取AI响应内容成功 - 内容长度: {}", content.length());

            // 解析JSON响应
            JsonNode jsonNode = objectMapper.readTree(content);
            log.debug("解析JSON响应成功 - 字段: {}", StreamSupport.stream(
                    Spliterators.spliteratorUnknownSize(jsonNode.fieldNames(), Spliterator.ORDERED),
                    false).collect(Collectors.toList()));

            AIResponseDTO aiResponse = new AIResponseDTO();
            aiResponse.setMode(mode);
            aiResponse.setTitle(jsonNode.has("title") ? jsonNode.get("title").asText() : null);
            aiResponse.setContent(jsonNode.has("content") ? jsonNode.get("content").asText() : null);
            aiResponse.setStructuredData(content);

            log.debug("设置AIResponse基本字段 - 标题: {}, 内容长度: {}",
                    aiResponse.getTitle(),
                    aiResponse.getContent() != null ? aiResponse.getContent().length() : 0);

            // 解析标签
            if (jsonNode.has("tags") && jsonNode.get("tags").isArray()) {
                List<String> tags = new ArrayList<>();
                jsonNode.get("tags").forEach(tag -> tags.add(tag.asText()));
                aiResponse.setSuggestedTags(tags.toArray(new String[0]));
                log.debug("解析标签成功 - 标签数量: {}", tags.size());
            }

            // 设置元数据
            Map<String, Object> metadataMap = new HashMap<>();
            metadataMap.put("model", response.get("model"));
            metadataMap.put("usage", response.get("usage"));
            aiResponse.setMetadata(objectMapper.writeValueAsString(metadataMap));

            // 设置创建时间
            aiResponse.setCreatedAt(LocalDateTime.now().toString());

            log.debug("创建笔记响应解析完成");
            return aiResponse;
        } catch (Exception e) {
            log.error("解析创建笔记响应失败 - 原因: {}", e.getMessage(), e);
            throw new RuntimeException("解析创建笔记响应失败: " + e.getMessage());
        }
    }

    /**
     * 解析编辑笔记模式的响应
     */
    private AIResponseDTO parseEditNoteResponse(Map<String, Object> response, String mode) {
        try {
            log.debug("开始解析编辑笔记响应 - 模式: {}", mode);

            // 提取AI响应内容
            Map<String, Object> choice = ((List<Map<String, Object>>) response.get("choices")).get(0);
            Map<String, Object> message = (Map<String, Object>) choice.get("message");
            String content = (String) message.get("content");
            log.debug("提取AI响应内容成功 - 内容长度: {}", content.length());

            // 解析JSON响应
            JsonNode jsonNode = objectMapper.readTree(content);
            log.debug("解析JSON响应成功 - 字段: {}", StreamSupport.stream(
                    Spliterators.spliteratorUnknownSize(jsonNode.fieldNames(), Spliterator.ORDERED),
                    false).collect(Collectors.toList()));

            AIResponseDTO aiResponse = new AIResponseDTO();
            aiResponse.setMode(mode);
            aiResponse.setStructuredData(content);

            // 根据不同模式提取不同字段
            switch (mode) {
                case "SUMMARIZE":
                    if (jsonNode.has("summary")) {
                        aiResponse.setContent(jsonNode.get("summary").asText());
                        log.debug("提取摘要字段成功 - 长度: {}", aiResponse.getContent().length());
                    }
                    break;

                case "ENHANCE":
                    if (jsonNode.has("enhancedContent")) {
                        aiResponse.setContent(jsonNode.get("enhancedContent").asText());
                        log.debug("提取增强内容字段成功 - 长度: {}", aiResponse.getContent().length());
                    }
                    break;

                case "EXTRACT_TAGS":
                    if (jsonNode.has("tags") && jsonNode.get("tags").isArray()) {
                        List<String> tags = new ArrayList<>();
                        jsonNode.get("tags").forEach(tag -> tags.add(tag.asText()));
                        aiResponse.setSuggestedTags(tags.toArray(new String[0]));
                        log.debug("提取标签字段成功 - 标签数量: {}", tags.size());
                    }
                    break;

                case "REWRITE":
                    if (jsonNode.has("rewrittenContent")) {
                        aiResponse.setContent(jsonNode.get("rewrittenContent").asText());
                        log.debug("提取改写内容字段成功 - 长度: {}", aiResponse.getContent().length());
                    }
                    break;

                default:
                    // 默认模式
                    if (jsonNode.has("feedback")) {
                        aiResponse.setContent(jsonNode.get("feedback").asText());
                        log.debug("提取反馈字段成功 - 长度: {}", aiResponse.getContent().length());
                    } else {
                        log.warn("未找到与模式 {} 匹配的内容字段", mode);
                    }
                    break;
            }

            // 设置元数据
            Map<String, Object> metadataMap = new HashMap<>();
            metadataMap.put("model", response.get("model"));
            metadataMap.put("usage", response.get("usage"));
            aiResponse.setMetadata(objectMapper.writeValueAsString(metadataMap));

            // 设置创建时间
            aiResponse.setCreatedAt(LocalDateTime.now().toString());

            log.debug("编辑笔记响应解析完成");
            return aiResponse;
        } catch (Exception e) {
            log.error("解析编辑笔记响应失败 - 原因: {}", e.getMessage(), e);
            throw new RuntimeException("解析编辑笔记响应失败: " + e.getMessage());
        }
    }

    /**
     * 保存对话历史
     */
    private AIConversation saveConversationHistory(Long userId, Long noteId, String mode,
            String prompt, String extraParams, Map<String, Object> response) {
        try {
            log.debug("开始保存对话历史 - 用户ID: {}, 笔记ID: {}, 模式: {}", userId, noteId, mode);

            AIConversation conversation = new AIConversation();
            conversation.setUserId(userId);
            conversation.setNoteId(noteId);
            conversation.setMode(mode);
            conversation.setPrompt(prompt);
            conversation.setExtraParams(extraParams);

            // 将response转为JSON字符串，但不记录过长内容
            String responseJson = objectMapper.writeValueAsString(response);
            conversation.setResponse(responseJson);
            log.debug("设置AI响应内容 - JSON长度: {}", responseJson.length());

            // 设置元数据
            Map<String, Object> metadataMap = new HashMap<>();
            if (response.containsKey("usage")) {
                metadataMap.put("usage", response.get("usage"));
                log.debug("添加使用情况到元数据: {}", response.get("usage"));
            }
            if (response.containsKey("model")) {
                metadataMap.put("model", response.get("model"));
                log.debug("添加模型信息到元数据: {}", response.get("model"));
            }
            String metadataJson = objectMapper.writeValueAsString(metadataMap);
            conversation.setMetadata(metadataJson);
            log.debug("设置元数据 - 长度: {}", metadataJson.length());

            // 设置时间
            LocalDateTime now = LocalDateTime.now();
            conversation.setCreatedAt(now);
            conversation.setUpdatedAt(now);
            conversation.setDeleted(0);

            // 保存
            log.debug("执行数据库插入操作");
            int affectedRows = aiConversationMapper.insert(conversation);
            log.info("对话历史保存成功 - ID: {}, 影响行数: {}", conversation.getId(), affectedRows);

            return conversation;
        } catch (Exception e) {
            log.error("保存对话历史失败 - 原因: {}", e.getMessage(), e);
            throw new RuntimeException("保存对话历史失败: " + e.getMessage());
        }
    }
}